#ifndef AFCORE_COMMON_CONFIG_CONFIG_
#define AFCORE_COMMON_CONFIG_CONFIG_

#include <string>
#include <vector>
#include <mutex>
#include <string_view>

#include <boost/property_tree/ini_parser.hpp>

#include "define.h"
#include "nocopyable.h"

namespace afcore {

namespace bpt = boost::property_tree;

/// @brief  配置文件管理器
/// @note   配置文件采用的ini格式的
class AFCORE_COMMON_API CConfigMgr
  : public CNocopyable {
public:
  /// @brief  单例
  /// @return 全局配置
  static CConfigMgr& Instance();

  /// @brief  加载配置
  /// @param  filename    配置文件名
  /// @param  args        配置参数
  /// @param  [out]   error   错误信息
  /// @param  reload      是否重载 默认false
  /// @return 加载成功true 失败false
  bool Load(std::string const& filename, std::vector<std::string> args, std::string& error, bool reload = false);

  /// @brief  重新加载
  /// @param  [out]   error   错误信息
  /// @return 加载成功true 失败false
  bool Reload(std::string& error);

  /// @brief  配置文件名
  /// @return 文件名
  std::string const& GetFilename();

  /// @brief  配置文件名
  /// @return 文件名
  std::string_view GetFilenameView();

  /// @brief  配置启动参数
  /// @return 启动参数
  std::vector<std::string> const& GetArguments() const;

  /// @brief  获取关键字
  /// @param  name    关键字名称
  /// @return 关键字名称对应的关键字
  std::vector<std::string> GetKeysByString(std::string const& name);

  /// @brief  获取string类型的值，没有就用默认值
  /// @param  name    属性名
  /// @param  def     string类型默认值
  /// @return 属性名对应的值
  std::string GetStringDefault(std::string const& name, const std::string& def) const;

  /// @brief  获取bool类型的值，没有就用默认值
  /// @param  name    属性名
  /// @param  def     bool类型默认值
  /// @return 属性名对应的值
  bool GetBoolDefault(std::string const& name, bool def) const;

  /// @brief  获取int类型的值，没有就用默认值
  /// @param  name    属性名
  /// @param  def     int类型默认值
  /// @return 属性名对应的值
  int32_t GetIntDefault(std::string const& name, int32_t def) const;

  /// @brief  获取int64类型的值，没有就用默认值
  /// @param  name    属性名
  /// @param  def     int64类型默认值
  /// @return 属性名对应的值
  int64_t GetInt64Default(std::string const& name, int64_t def) const;

  /// @brief  获取float类型的值，没有就用默认值
  /// @param  name    属性名
  /// @param  def     float类型默认值
  /// @return 属性名对应的值
  float GetFloatDefault(std::string const& name, float def) const;

private:
  /// @brief  模板取值
  /// @tparam T       默认值类型
  /// @param  [in]    name  关键字的名称
  /// @param  [in]    def   T类型默认值
  /// @return T类型的key为name的值
  template<class T>
  T GetValueDefault(std::string const& name, T def) const;

private:
  std::string filename_;            ///< 配置文件名
  std::vector<std::string> args_;   ///< 配置启动时参数
  bpt::ptree config_;               ///< 配置文件树
  std::mutex config_mutex_;         ///< 配置互斥锁
};

} // !namespace afcore

#endif // !AFCORE_COMMON_CONFIG_CONFIG_